package org.ytu.classifier.algorithm;

import org.ytu.classifier.wavApi.WavFile;
import org.ytu.classifier.wavApi.WavFileIO;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Partitioner extends WavFileIO {
   private int samplingRate = 11025;

   public void startPartition(File fileToRemoveSilence) {
      String fileNameToPartition = removeSilence(fileToRemoveSilence);
      partition(fileNameToPartition);
   }

   //wav dosyasındaki sessiz kısımlar çıkartılıyor
   public String removeSilence(File fileToRemoveSilence) {
      try {
         WavFile wavFile = WavFile.openWavFile(fileToRemoveSilence);
         List<Double> allBuffer;
         wavFile.display();

         allBuffer = readFrames(wavFile);

         double totalEnergy = 0;
         double[] entropy = new double[allBuffer.size() - 56];
         for (int n = 0; n < allBuffer.size() - 56; n++) {
            double sampleEnergy = 0;
            for (int k = 0; k <= 56; k++) {
               sampleEnergy += Math.pow(allBuffer.get(n + k), 2);
            }
            entropy[n] = sampleEnergy;
            totalEnergy += sampleEnergy;
         }

         allBuffer = allBuffer.subList(0, entropy.length);
         double averageEnergy = totalEnergy / entropy.length;
         double tresholdEnergy = averageEnergy / 3;

         List<Double> cleanedList = new ArrayList<Double>();

         for (int n = 0; n < entropy.length; n++) {
            if (entropy[n] > tresholdEnergy) {
               cleanedList.add(allBuffer.get(n));
            }
         }

         int cleanBufferLength = cleanedList.size();
         double[] cleanBuffer = new double[cleanBufferLength];
         for (int i = 0; i < cleanBufferLength; i++) {
            cleanBuffer[i] = cleanedList.get(i);
         }

         String cleanedFileName = fileToRemoveSilence.getPath();
         cleanedFileName = cleanedFileName.substring(0, cleanedFileName.lastIndexOf(".")) + "_cleaned.wav";
         WavFile cleanedWavFile = WavFile.newWavFile(new File(cleanedFileName), 1, cleanBufferLength, 16, samplingRate);
         cleanedWavFile.writeFrames(cleanBuffer, cleanBufferLength);
         System.out.println("***********************************");
         cleanedWavFile.display();

         wavFile.close();
         cleanedWavFile.close();
         return cleanedFileName;

      } catch (Exception e) {
         System.err.println(e);
      }
      return null;
   }

   //1'er saniyelik parçalara ayırma işlemi yapılıyor
   public void partition(String fileName) {
      try {
         WavFile wavFile = WavFile.openWavFile(new File(fileName));
         wavFile.display();
         int sampleRate = (int) wavFile.getSampleRate();
         double duration = 1.0;
         long numFrames = (long) (duration * sampleRate);

         double[] buffer = new double[(int) numFrames];

         int framesRead = -1;//while döngüsüne ilk sefer girebilsin diye atandı
         long remaining;
         int i = 1;
         remaining = wavFile.getFramesRemaining();
         while ((remaining >= numFrames) && (framesRead != 0)) {
            int toWrite = (int) numFrames;
            framesRead = wavFile.readFrames(buffer, (int) numFrames);

            String partitionedFileName = fileName;
            partitionedFileName = partitionedFileName.substring(0, partitionedFileName.lastIndexOf("_"));
            WavFile wavFilePart = WavFile.newWavFile(new File(partitionedFileName + "_" + i + ".wav"), 1, numFrames, 16, sampleRate);
            i++;
            wavFilePart.writeFrames(buffer, toWrite);
            wavFilePart.close();
            remaining = wavFile.getFramesRemaining();
         }
         wavFile.close();
      } catch (Exception e) {
         System.err.println(e);
      }
   }
}
